package mylib.dir;

/**
 * Created with IntelliJ IDEA.
 * User: 1
 * Date: 10.08.12
 * Time: 15:06
 * To change this template use File | Settings | File Templates.
 */
public class Plane implements Comparable<Plane> {

    public long A, B, C, D;

    public Plane(Point3d a, Point3d b, Point3d c) {
        A = GeometryUtils.determinant(b.y - a.y, b.z - a.z, c.y - a.y, c.z - a.z);
        B = -GeometryUtils.determinant(b.x - a.x, b.z - a.z, c.x - a.x, c.z - a.z);
        C = GeometryUtils.determinant(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
        D = -A * a.x - B * a.y - C * a.z;
        norm();
    }

    private void norm() {
        long g = MathUtils.gcd(A, MathUtils.gcd(B, MathUtils.gcd(C, D)));
        if (g != 0) {
            A /= g;
            B /= g;
            C /= g;
            D /= g;
        }
        if (A < 0 || A == 0 && B < 0 || A == 0 && B == 0 && C < 0 || A == 0 && B == 0 && C == 0 && D < 0) {
            A = -A;
            B = -B;
            C = -C;
            D = -D;
        }
    }

    public long sign(Point3d point3d) {
        return A * point3d.x + B * point3d.y + C * point3d.z + D;
    }

    @Override
    public int compareTo(Plane o) {
        if (A != o.A)
            return Long.signum(A - o.A);
        if (B != o.B)
            return Long.signum(B - o.B);
        if (C != o.C)
            return Long.signum(C - o.C);
        return Long.signum(D - o.D);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Plane plane = (Plane) o;

        if (A != plane.A) return false;
        if (B != plane.B) return false;
        if (C != plane.C) return false;
        if (D != plane.D) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = (int) (A ^ (A >>> 32));
        result = 31 * result + (int) (B ^ (B >>> 32));
        result = 31 * result + (int) (C ^ (C >>> 32));
        result = 31 * result + (int) (D ^ (D >>> 32));
        return result;
    }
}
